home *** CD-ROM | disk | FTP | other *** search
/ Netscape Plug-Ins Developer's Kit / Netscape_Plug-Ins_Developers_Kit.iso / CGIPERL / MACPERL / MSRCE418.HQX / Perl Source ƒ / MacPerl / MPUtils.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-27  |  24.6 KB  |  1,023 lines

  1. /*********************************************************************
  2. Project    :    MacPerl            -    Real Perl Application
  3. File        :    MPEditUtils.c    -
  4. Author    :    Matthias Neeracher
  5.  
  6. A lot of this code is borrowed from 7Edit written by
  7. Apple Developer Support UK
  8.  
  9. Language    :    MPW C
  10.  
  11. $Log: MPUtils.c,v $
  12. Revision 1.2  1994/05/04  02:52:40  neeri
  13. Inline Input.
  14.  
  15. Revision 1.1  1994/02/27  23:02:08  neeri
  16. Initial revision
  17.  
  18. Revision 0.5  1993/08/17  00:00:00  neeri
  19. DoPrefDialog()
  20.  
  21. Revision 0.4  1993/08/15  00:00:00  neeri
  22. DoAbout
  23.  
  24. Revision 0.3  1993/08/14  00:00:00  neeri
  25. Preference file
  26.  
  27. Revision 0.2  1993/05/30  00:00:00  neeri
  28. Support Console Windows
  29.  
  30. Revision 0.1  1993/05/29  00:00:00  neeri
  31. Compiles correctly
  32.  
  33. *********************************************************************/
  34.  
  35. #include <PLStringFuncs.h>
  36. #include <Events.h>
  37. #include <Traps.h>
  38. #include <Dialogs.h>
  39. #include <Fonts.h>
  40. #include <Packages.h>
  41. #include <ToolUtils.h>
  42. #include <AppleEvents.h>
  43. #include <TFileSpec.h>
  44. #include <Folders.h>
  45. #include <Resources.h>
  46. #include <OSUtils.h>
  47. #include <Files.h>
  48. #include <Lists.h>
  49. #include <Icons.h>
  50. #include <TSMTE.h>
  51. #include <string.h>
  52. #include <GUSI.h>
  53. #include <Desk.h>
  54. #include <ctype.h>
  55. #include <stdio.h>
  56.  
  57. #include "MPUtils.h"
  58. #include "MPWindow.h"
  59. #include <patchlevel.h>
  60.  
  61. /**-----------------------------------------------------------------------
  62.         Name:         ShowError
  63.         Purpose:        Reports an error to the user as both string and number.
  64.     -----------------------------------------------------------------------**/
  65. #if !defined(powerc) && !defined(__powerc)
  66. #pragma segment Utils
  67. #endif
  68.  
  69. pascal void ShowError(Str255 theError, long theErrorCode)
  70. {
  71.     short     alertResult;
  72.     Str255    theString;
  73.  
  74.     if (gAppleEventsImplemented)
  75.         if (AEInteractWithUser(kAEDefaultTimeout, nil,nil))
  76.             return;
  77.         
  78.      SetCursor(&qd.arrow);
  79.      NumToString(theErrorCode, theString);
  80.      ParamText(theError, theString, (StringPtr) "\p", (StringPtr) "\p");
  81.      alertResult = Alert(300, nil);
  82. } /* ShowError */
  83.  
  84. /**-----------------------------------------------------------------------
  85.         Name:         Ours
  86.         Purpose:        Checks the frontmost window belongs to the app.
  87.     -----------------------------------------------------------------------**/
  88. #if !defined(powerc) && !defined(__powerc)
  89. #pragma segment Utils
  90. #endif
  91.  
  92. pascal Boolean Ours(WindowPtr aWindow)
  93. {
  94.     if (aWindow)
  95.         if (((WindowPeek)aWindow)->windowKind == PerlWindowKind)
  96.             return(true);
  97.  
  98.     return(false);
  99. } /* Ours */
  100.  
  101. /**-----------------------------------------------------------------------
  102.         Name:         SetShortMenus
  103.         Purpose:        Cuts the menus down to a minimum - Apple File Edit.
  104.                         Greys out the unavailable options - used when no docs open
  105.     -----------------------------------------------------------------------**/
  106. #if !defined(powerc) && !defined(__powerc)
  107. #pragma segment Utils
  108. #endif
  109.  
  110. pascal void SetShortMenus()
  111. {
  112.     DeleteMenu(windowID);
  113.  
  114.     DrawMenuBar();
  115. }  /* SetShortMenus */
  116.  
  117. /**-----------------------------------------------------------------------
  118.         Name:         SetLongMenus
  119.         Purpose:        Reinstates the full menu bar - called when first document
  120.                     opened.
  121.     -----------------------------------------------------------------------**/
  122. #if !defined(powerc) && !defined(__powerc)
  123. #pragma segment Utils
  124. #endif
  125.  
  126. pascal void SetLongMenus()
  127. {
  128.     InsertMenu(myMenus[windowM], perlID);
  129.  
  130.     DrawMenuBar();
  131. }  /* SetLongMenus */
  132.  
  133. /**-----------------------------------------------------------------------
  134.     Name:       SetEditMenu
  135.     Purpose:    Set the text of the edit menu according to the state of
  136.                      current document.
  137.   -----------------------------------------------------------------------**/
  138.  
  139. #if !defined(powerc) && !defined(__powerc)
  140. #pragma segment Utils
  141. #endif
  142.  
  143. pascal void SetEditMenu(DPtr theDoc)
  144. {
  145. #ifndef RUNTIME
  146.     if (theDoc->kind == kDocumentWindow && theDoc->u.reg.showBorders)
  147.         SetItem(myMenus[editM], cBorders, (StringPtr) "\pHide Borders");
  148.     else
  149.         SetItem(myMenus[editM], cBorders, (StringPtr) "\pShow Borders");
  150. #endif
  151. }  /* SetEditMenu */
  152.  
  153. /**-----------------------------------------------------------------------
  154.     Name:       GetTempFSSpec
  155.     Purpose:    Fills newstring create temporary file specification.
  156.   -----------------------------------------------------------------------**/
  157.  
  158. #if !defined(powerc) && !defined(__powerc)
  159. #pragma segment Utils
  160. #endif
  161.  
  162. pascal void GetTempFSSpec(DPtr aDoc, FSSpec * temp)
  163. {
  164. #ifndef RUNTIME
  165.     Special2FSSpec(kTempFileType, aDoc->theFSSpec.vRefNum, 0, temp);
  166. #else
  167.     Special2FSSpec(
  168.         kTempFileType, 
  169.         aDoc->theFSSpec.vRefNum, aDoc->theFSSpec.parID, 
  170.         temp);
  171. #endif
  172. }
  173.  
  174. /**-----------------------------------------------------------------------
  175.     Name:       SetText
  176.     Purpose:    Sets the text of the supplied itemNo in aDialog to
  177.                     theString and select it.
  178.   -----------------------------------------------------------------------**/
  179.  
  180. #if !defined(powerc) && !defined(__powerc)
  181. #pragma segment Utils
  182. #endif
  183.  
  184. pascal void SetText(DialogPtr aDialog, short itemNo, Str255 theString)
  185. {
  186.     Handle      itemHandle;
  187.     Rect        box;
  188.     short       kind;
  189.     TEHandle    theTEHandle;
  190.  
  191.     GetDItem(aDialog, itemNo, &kind, &itemHandle, &box);
  192.     SetIText(itemHandle, theString);
  193.  
  194.     theTEHandle = ((DialogPeek)aDialog)->textH;
  195.  
  196.     /*set all the text to be selected*/
  197.     if (theTEHandle)
  198.         TESetSelect(0, 255, theTEHandle);
  199. }
  200.  
  201. /**-----------------------------------------------------------------------
  202.     Name:       RetrieveText
  203.     Purpose:    Returns the text of anItem in aDialog in aString.
  204.   -----------------------------------------------------------------------**/
  205.  
  206. #if !defined(powerc) && !defined(__powerc)
  207. #pragma segment Utils
  208. #endif
  209.  
  210. pascal void RetrieveText(DialogPtr aDialog, short anItem, Str255 aString)
  211. {
  212.     short      kind;
  213.     Rect       box;
  214.     Handle     itemHandle;
  215.  
  216.     GetDItem(aDialog, anItem, &kind, &itemHandle, &box);
  217.     GetIText(itemHandle, aString);
  218. }
  219.  
  220. /**-----------------------------------------------------------------------
  221.     Name:      DrawDefaultOutline
  222.     Purpose:   Draws an outline around theItem.
  223.                     Called as a useritem Proc by the dialog manager.
  224.                     To use place a useritem over the default item in the
  225.                     dialog and install the address of this proc as the item
  226.                     handle.
  227.   -----------------------------------------------------------------------**/
  228.  
  229. #if !defined(powerc) && !defined(__powerc)
  230. #pragma segment Utils
  231. #endif
  232.  
  233. pascal void DrawDefaultOutline(DialogPtr theDialog, short theItem)
  234. {
  235.     short       kind;
  236.     Handle      itemHandle;
  237.     Rect        box;
  238.  
  239.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  240.     PenSize(3, 3);
  241.     InsetRect(&box, -4, -4);
  242.     FrameRoundRect(&box, 16, 16);
  243.     PenNormal();
  244. }  /* DrawDefaultOutline */
  245.  
  246. #if USESROUTINEDESCRIPTORS
  247. RoutineDescriptor    uDrawDefaultOutline = 
  248.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawDefaultOutline);
  249. #endif
  250.  
  251. /**-----------------------------------------------------------------------
  252.     Name:       AdornDefaultButton
  253.     Purpose:    Installs DrawDefaultOutline as the useritem proc
  254.                      for the given item.
  255. -----------------------------------------------------------------------**/
  256.  
  257. #if !defined(powerc) && !defined(__powerc)
  258. #pragma segment Utils
  259. #endif
  260.  
  261. pascal void AdornDefaultButton(DialogPtr theDialog,short theItem)
  262. {
  263.     short        kind;
  264.     Handle    itemHandle;
  265.      Rect        box;
  266.  
  267.     GetDItem(theDialog, theItem, &kind, &itemHandle, &box);
  268.     SetDItem(theDialog, theItem, kind, (Handle)&uDrawDefaultOutline, &box);
  269. }
  270.  
  271. pascal void GetRectOfDialogItem(DialogPtr theDialog, short theItem, Rect *theRect)
  272. {
  273.     short       kind;
  274.     Handle      itemHandle;
  275.  
  276.     GetDItem(theDialog, theItem, &kind, &itemHandle, theRect);
  277. }
  278.  
  279. /**------  FeatureIsImplemented    ------------**/
  280. /*    This is called to use Gestalt to determine if a feature is implemented.
  281.      This applies to only those referenced by OSType    */
  282.  
  283. #if !defined(powerc) && !defined(__powerc)
  284. #pragma segment Utils
  285. #endif
  286.  
  287. pascal Boolean FeatureIsImplemented(OSType theFeature, short theTestBit)
  288. {
  289.      long      result;
  290.  
  291.     return !Gestalt(theFeature, &result) && (result & (1 << theTestBit));
  292. }
  293.  
  294. #if !defined(powerc) && !defined(__powerc)
  295. #pragma segment Utils
  296. #endif
  297.  
  298. pascal Boolean CheckEnvironment()
  299. {
  300.     long result;
  301.     
  302.     /*check for the AppleEvents manager - we certainly can't work without it*/
  303.  
  304.     gAppleEventsImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr, gestaltAppleEventsPresent);
  305.  
  306. #ifndef RUNTIME
  307.     /*first check if the Edition Manager is present*/
  308.  
  309.     gEditionManagerImplemented = FeatureIsImplemented(gestaltEditionMgrAttr, gestaltEditionMgrPresent);
  310.  
  311.     /*and for good measure- the Alias manager*/
  312.  
  313.     gAliasManagerImplemented  = FeatureIsImplemented(gestaltAliasMgrAttr, gestaltAliasMgrPresent);
  314.  
  315.     /*check if recording is implemented*/
  316.  
  317.     gRecordingImplemented   = FeatureIsImplemented(gestaltAppleEventsAttr,1);
  318.  
  319.     /*check for the Outline fonts*/
  320.  
  321.     gOutlineFontsImplemented  = FeatureIsImplemented(gestaltFontMgrAttr, gestaltOutlineFonts);
  322.  
  323.     /* check for Text Services and TSMTE */
  324.     gTextServicesImplemented = !Gestalt(gestaltTSMgrVersion, &result) && (result > 0);
  325.     gTSMTEImplemented    = FeatureIsImplemented(gestaltTSMTEAttr, gestaltTSMTEPresent);
  326.  
  327.     return     gEditionManagerImplemented &&
  328.                 gAliasManagerImplemented   &&
  329.                 gAppleEventsImplemented    &&
  330.                 gOutlineFontsImplemented;
  331. #else
  332.     return true;
  333. #endif
  334. }  /* CheckEnvironment */
  335.  
  336. /*
  337.     DoPageSetup returns true if the page setup of the document is altered
  338. */
  339.  
  340. pascal Boolean DoPageSetup(DPtr theDoc)
  341. {
  342.     if (theDoc) {
  343.         Boolean result;
  344.  
  345.         PrOpen();
  346.         result =  PrStlDialog(theDoc->thePrintSetup);
  347.         PrClose();
  348.  
  349.         return(result);
  350.     }
  351. }  /* DoPageSetup */
  352.  
  353. /*
  354.     Name:    CtrlKeyPressed
  355.     Purpose: Returns true if control key pressed during event
  356. */
  357. pascal Boolean CtrlKeyPressed(const EventRecord *theEvent)
  358. {
  359.     return theEvent->modifiers & controlKey;
  360. }
  361.  
  362. /*
  363.     Name:    OptionKeyPressed
  364.     Purpose: Returns true if option key pressed during event
  365. */
  366. pascal Boolean OptionKeyPressed(const EventRecord *theEvent)
  367. {
  368.     return theEvent->modifiers & optionKey;
  369. }
  370.  
  371. pascal void DrawVersion(DialogPtr dlg, short item)
  372. {
  373.     VersRecHndl    vers;
  374.     short            base;
  375.     Handle        h;
  376.     Rect            r;
  377.     FontInfo        info;
  378.     Str15            patchlevel;
  379.  
  380.     GetDItem(dlg, item, &base, &h, &r);
  381.     SetPort(dlg);
  382.     TextFont(1);
  383.     TextSize(10);
  384.     GetFontInfo(&info);
  385.     
  386.     base = r.top+2+info.ascent;
  387.     MoveTo(r.left+2, base);
  388.     DrawString((StringPtr) "\pVersion");
  389.     MoveTo((r.left+r.right) >> 1, r.top+2+info.ascent);
  390.     
  391.     vers = (VersRecHndl) GetResource('vers', 1);
  392.     HLock((Handle) vers);
  393.     DrawString((*vers)->shortVersion);
  394.     ReleaseResource((Handle) vers);
  395.  
  396.     base += info.ascent + info.descent + info.leading;
  397.     MoveTo(r.left+2, base);
  398.     DrawString((StringPtr) "\pPatchlevel");
  399.     MoveTo((r.left+r.right) >> 1, base);
  400.     patchlevel[0] = sprintf((char *) patchlevel+1, "%d", PATCHLEVEL);
  401.     DrawString(patchlevel);
  402.  
  403.     TextFont(CreditID);
  404.     TextSize(12);
  405. }
  406.  
  407. #if USESROUTINEDESCRIPTORS
  408. RoutineDescriptor    uDrawVersion = 
  409.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, DrawVersion);
  410. #else
  411. #define uDrawVersion *(UserItemUPP)&DrawVersion
  412. #endif
  413.  
  414. pascal void DoAbout()
  415. {
  416.     DialogPtr    dlg;
  417.     short            kind;
  418.     Handle        hdl;
  419.     Rect            bounds;
  420.     Rect             hot;
  421.     Str255        string;
  422.     short *        widths;
  423.     short            count;
  424.     short            current;
  425.     short            offset;
  426.     EventRecord    ev;
  427.     RgnHandle    rgn;
  428.     long            lastTicks;
  429.     WindowPtr    win;
  430.     
  431.     SetCursor(&qd.arrow);
  432.     
  433.     dlg = GetNewDialog(AboutDialog, nil, (WindowPtr) -1);
  434.  
  435.     GetDItem(dlg, 2, &kind, &hdl, &bounds);
  436.     SetDItem(dlg, 2, kind, (Handle) &uDrawVersion, &bounds);
  437.     
  438.     DrawDialog(dlg);
  439. #ifndef RUNTIME
  440.     GetDItem(dlg, 1, &kind, &hdl, &bounds);
  441.     SetPort(dlg);
  442.     TextFont(CreditID);
  443.     TextSize(12);
  444.     TextFace(normal);
  445.     ClipRect(&bounds);
  446.     hot         =     bounds;
  447.     hot.left    =    hot.right-2;
  448.     
  449.     kind         = StringWidth((StringPtr) "\p Ñ ");
  450.     hdl         = GetResource('STR#', CreditID);
  451.     count        = **(short **) hdl;
  452.     widths     = (short *) NewPtr(2 * count);
  453.     
  454.     for (current = 0; current<count; ++current) {
  455.         GetIndString(string, CreditID, current+1);
  456.         widths[current] = StringWidth(string) + kind;
  457.     }
  458.     
  459.     offset     =     0;
  460.     current     =     0;
  461.     rgn        =    NewRgn();
  462.     lastTicks=    0;
  463.     GetIndString(string, CreditID, current+1);
  464. #endif
  465.  
  466.     while (dlg) {
  467. #ifndef RUNTIME
  468. #if defined(powerc) || defined(_powerc)
  469. #define STEP 1
  470. #else
  471. #define STEP 2
  472. #endif
  473.         while (TickCount() < lastTicks + STEP);
  474.         
  475.         lastTicks = TickCount();
  476.         
  477.         SetPort(dlg);
  478.         
  479.         ScrollRect(&bounds, -STEP, 0, rgn);
  480.         
  481.         ClipRect(&hot);
  482.         MoveTo(bounds.right - offset, bounds.bottom - 3);
  483.         DrawString(string);
  484.         DrawString((StringPtr) "\p Ñ ");
  485.         ClipRect(&bounds);
  486.         
  487.         if ((offset += STEP) >= widths[current]) {
  488.             current = (current+1) % count;
  489.             offset  = 0;
  490.             GetIndString(string, CreditID, current+1);
  491.         }
  492. #endif
  493.  
  494.         if (WaitNextEvent(mDownMask+keyDownMask+activMask+updateMask+osMask, &ev, 1, nil))
  495.             switch (ev.what) {
  496.             case activateEvt:
  497.                 if ((WindowPtr) ev.message != dlg)
  498.                     DoActivate((WindowPtr)ev.message, (ev.modifiers & activeFlag) != 0);
  499.                     
  500.                 break;
  501.     
  502.             case updateEvt:
  503.                 win = (WindowPtr) ev.message;
  504.                 if (win == dlg) {
  505.                     BeginUpdate(dlg);
  506.                     UpdtDialog(dlg, dlg->visRgn);
  507.                     EndUpdate(dlg);
  508.                 } else
  509.                     DoUpdate(DPtrFromWindowPtr(win), win);
  510.                 break;
  511.     
  512.             case kOSEvent:
  513.                 switch (ev.message & osEvtMessageMask) { /*high byte of message*/
  514.                 case 0x01000000:
  515.                         gInBackground = ((ev.message & resumeFlag) == 0);
  516.                 }
  517.                 if (!gInBackground)
  518.                     break;
  519.             default:
  520.                 DisposeDialog(dlg);
  521.                 
  522.                 dlg = nil;
  523.                 break;
  524.             }
  525.     }
  526. }
  527.  
  528. static void CenterWindow(DialogPtr dlg)
  529. {
  530.     Rect    *        screen;
  531.     short            hPos;
  532.     short            vPos;
  533.     
  534.     screen    =    &qd.screenBits.bounds;
  535.     hPos    =    screen->right+screen->left-dlg->portRect.right >> 1;
  536.     vPos    =    (screen->bottom-screen->top-dlg->portRect.bottom)/3;
  537.     vPos    +=    screen->top;
  538.     MoveWindow(dlg, hPos, vPos, true);
  539. }    
  540.  
  541. #ifdef RUNTIME
  542.  
  543. typedef long ICON[32];
  544. typedef struct    {
  545.     ICON    icon;
  546.     ICON    mask;
  547. } ICN_;
  548.  
  549. typedef short icm[12];
  550. typedef struct {
  551.     icm    icon;
  552.     icm     mask;
  553. } icm_;
  554.  
  555. static void PlotICN_(ICN_ * icon, Rect * within, IconMode mode)
  556. {
  557.     GrafPtr    port;
  558.     BitMap    bmap;
  559.     BitMap    mask;
  560.     PenState    ps;
  561.     Pattern    ltGray;
  562.     long    *    lg;
  563.     
  564.     GetPort(&port);
  565.     bmap.baseAddr        =    (Ptr) icon;
  566.     bmap.rowBytes        =    4;
  567.     bmap.bounds.top    =    0;
  568.     bmap.bounds.left    =    0;
  569.     bmap.bounds.bottom=    32;
  570.     bmap.bounds.right    =    32;
  571.     
  572.     mask = bmap;
  573.     mask.baseAddr        =    (Ptr) icon->mask;
  574.     
  575.     switch (mode)    {
  576.     case iconGray:
  577.         GetPenState(&ps);
  578.         PenMode(patXor);
  579.         lg     =  (long *)<Gray;
  580.         lg[0] =    0x11004400;
  581.         lg[1] =    lg[0];
  582.         PenPat(<Gray);
  583.         PaintRect(within);
  584.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  585.         PaintRect(within);
  586.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcOr, nil);
  587.         SetPenState(&ps);
  588.         break;
  589.     case iconHilited:
  590.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcOr, nil);
  591.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  592.         break;
  593.     default:
  594.         CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  595.         CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  596.         break;
  597.     }
  598. }
  599.  
  600. pascal void PlotResICN_(short id, Rect * within, IconMode mode)
  601. {
  602.     char        flags;
  603.     ICN_ **  icon;
  604.     
  605.     if (icon = (ICN_ **) GetResource('ICN#', id))    {
  606.         flags    =    HGetState((Handle) icon);
  607.         HLock((Handle) icon);
  608.         PlotICN_(*icon, within, mode);
  609.         HSetState((Handle) icon, flags);
  610.     }
  611. }
  612.  
  613. static void PlotMiniIcon(icm_ * icon, Rect * within)
  614. {
  615.     GrafPtr    port;
  616.     BitMap    bmap;
  617.     BitMap    mask;
  618.     
  619.     GetPort(&port);
  620.     bmap.baseAddr        =    (Ptr) icon;
  621.     bmap.rowBytes        =    2;
  622.     bmap.bounds.top    =    0;
  623.     bmap.bounds.left    =    0;
  624.     bmap.bounds.bottom=    12;
  625.     bmap.bounds.right    =    16;
  626.     
  627.     mask = bmap;
  628.     mask.baseAddr        =    (Ptr) icon->mask;
  629.     
  630.     CopyBits(&mask, &port->portBits, &mask.bounds, within, srcBic, nil);
  631.     CopyBits(&bmap, &port->portBits, &bmap.bounds, within, srcXor, nil);
  632. }
  633.  
  634. pascal void PlotResMiniIcon(short id, Rect * within)
  635. {
  636.     char        flags;
  637.     icm_ **  icon;
  638.     
  639.     if (icon = (icm_ **) GetResource('icm#', id))    {
  640.         flags    =    HGetState((Handle) icon);
  641.         HLock((Handle) icon);
  642.         PlotMiniIcon(*icon, within);
  643.         HSetState((Handle) icon, flags);
  644.     }
  645. }
  646.  
  647. typedef struct {
  648.       Handle  handle;     /* handle or procedure pointer for this item */
  649.       Rect    bounds;     /* display rectangle for this item */
  650.       char    type;       /* item type - 1 */
  651.       char    data[1];    /* length byte of data */
  652.  } DialogItem;
  653.  
  654. typedef struct {
  655.       short            max_index; /* number of items - 1 */
  656.       DialogItem    items[1]; /* first item in the array */
  657.  } **ItemListHandle;
  658.  
  659. pascal void Append_DITL(DialogPtr dialog, short item_list_ID)
  660. {
  661.     ItemListHandle append_item_list;    /* handle to DITL being appended */
  662.     DialogItem *    item;                /* pointer to item being appended */
  663.     ItemListHandle    dlg_item_list;       /* handle to DLOG's item list */
  664.     short                i;
  665.     short                sz;
  666.     
  667.     dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
  668.     append_item_list = (ItemListHandle)GetResource('DITL', item_list_ID);
  669.     if (!append_item_list)
  670.       return;
  671.  
  672.    HLock((Handle)append_item_list);
  673.        
  674.     item = (*append_item_list)->items;
  675.     
  676.     for (i=0; i<=(*append_item_list)->max_index; ++i) {
  677.           switch (item->type & 0x7F) {
  678.         case ctrlItem + btnCtrl:
  679.         case ctrlItem + chkCtrl:
  680.         case ctrlItem + radCtrl:
  681.             item->handle = 
  682.                 (Handle)
  683.                     NewControl(
  684.                         (DialogPtr) dialog, &item->bounds,
  685.                         (StringPtr)item->data,
  686.                         true, 0, 0, 1,
  687.                         item->type & 0x03,
  688.                         0);
  689.             break;
  690.  
  691.         case ctrlItem + resCtrl :
  692.             item->handle = (Handle)GetNewControl(*(int*)(item->data + 1), (DialogPtr) dialog);
  693.             (**(ControlHandle)item->handle).contrlRect = item->bounds;
  694.             break;
  695.  
  696.         case statText :
  697.         case editText :
  698.             PtrToHand(item->data + 1, &item->handle, item->data[0]);
  699.             break;
  700.  
  701.         case iconItem :
  702.             item->handle = GetIcon(*(int*)(item->data + 1));
  703.             break;
  704.  
  705.         case picItem :
  706.             item->handle = (Handle)GetPicture(*(int*)(item->data + 1));
  707.             break;
  708.  
  709.         default :
  710.             item->handle = NULL;
  711.           }
  712.  
  713.       sz = (item->data[0] + 1) & 0xFFFE;
  714.       item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
  715.    }
  716.  
  717.       PtrAndHand(
  718.         (*append_item_list)->items,
  719.       (Handle)dlg_item_list,
  720.       GetHandleSize((Handle) append_item_list) - 2);
  721.    (*dlg_item_list)->max_index += (*append_item_list)->max_index + 1;
  722.    HUnlock((Handle) append_item_list);
  723.    ReleaseResource((Handle) append_item_list);
  724. }
  725.  
  726. pascal void Shorten_DITL(DialogPtr dialog, short shorten)
  727. {
  728.     DialogItem *    item;                /* pointer to item being appended */
  729.     ItemListHandle    dlg_item_list;       /* handle to DLOG's item list */
  730.     short                i;
  731.     short                sz;
  732.     short                restSize = -1;
  733.     
  734.     dlg_item_list = (ItemListHandle) ((DialogPeek)dialog)->items;
  735.  
  736.    HLock((Handle)dlg_item_list);
  737.        
  738.     item         = (*dlg_item_list)->items;
  739.     shorten     = (*dlg_item_list)->max_index - shorten;
  740.     
  741.     for (i=0; i<=(*dlg_item_list)->max_index; ++i) {
  742.         if (i > shorten)
  743.             switch (item->type & 0x7F) {
  744.             case ctrlItem + btnCtrl:
  745.             case ctrlItem + chkCtrl:
  746.             case ctrlItem + radCtrl:
  747.             case ctrlItem + resCtrl :
  748.                 DisposeControl((ControlHandle) item->handle);
  749.                 break;
  750.     
  751.             case statText :
  752.             case editText :
  753.                 DisposeHandle(item->handle);
  754.                 break;
  755.     
  756.             case iconItem :
  757.             case picItem :
  758.                 ReleaseResource(item->handle);
  759.                 break;
  760.     
  761.             default :
  762.                 break;
  763.             }
  764.  
  765.       sz = (item->data[0] + 1) & 0xFFFE;
  766.       item = (DialogItem *)((char*)item + sz + sizeof(DialogItem));
  767.         
  768.         if (i == shorten)
  769.             restSize = (char *) item - (char *) *dlg_item_list;
  770.    }
  771.  
  772.      if (restSize >= 0) {
  773.           SetHandleSize((Handle) dlg_item_list, restSize);
  774.         
  775.        (*dlg_item_list)->max_index = shorten;
  776.     }
  777.     
  778.    HUnlock((Handle) dlg_item_list);
  779. }
  780.  
  781. pascal short Count_DITL(DialogPtr dialog)
  782. {
  783.     return (*(ItemListHandle) ((DialogPeek)dialog)->items)->max_index + 1;
  784. }
  785.  
  786. #endif
  787.  
  788. pascal void Separator(DialogPtr dlg, short item)
  789. {
  790.     short        kind;
  791.     Handle    h;
  792.     Rect        r;
  793.     
  794.     PenPat(&qd.gray);
  795.     GetDItem(dlg, item, &kind, &h, &r);
  796.     FrameRect(&r);
  797.     PenPat(&qd.black);
  798. }
  799.  
  800. #if USESROUTINEDESCRIPTORS
  801. RoutineDescriptor    uSeparator = 
  802.         BUILD_ROUTINE_DESCRIPTOR(uppUserItemProcInfo, Separator);
  803. #endif
  804.  
  805. static DPtr        Documents[50];
  806. static short    DocCount = 0;
  807.  
  808. pascal void RegisterDocument(DPtr doc)
  809. {
  810.     Documents[DocCount++] = doc;
  811. }
  812.  
  813. pascal void UnregisterDocument(DPtr doc)
  814. {
  815.     short    i,j;
  816.     
  817.     for (i = 0, j = 0; i < DocCount; ++i)
  818.         if (Documents[i] != doc)
  819.             Documents[j++] = Documents[i];
  820.     
  821.     DocCount = j;
  822. }
  823.  
  824. pascal void SetupWindowMenu()
  825. {
  826.     short            i;
  827.     short            item = 0;
  828.     WindowPtr    front;
  829.      WindowPeek    aWindow;
  830.     WindowPeek    nextWindow;
  831.     MenuHandle    menu;
  832.     Str255        name;
  833.     int             needsSeparator = 0;
  834.     
  835.     DisposeMenu(myMenus[windowM]);
  836.     menu = myMenus[windowM]    = GetMenu(windowID);
  837.     
  838.     front = FrontWindow();
  839.     
  840.     for (i = 0; i < DocCount; ++i)
  841.         if (Documents[i]->kind != kDocumentWindow) {
  842.             AppendMenu(menu, (StringPtr) "\px");
  843.             GetWTitle(Documents[i]->theWindow, name);
  844.             SetMenuItemText(menu, ++item, name);
  845.             
  846.             if (!((WindowPeek) Documents[i]->theWindow)->visible)
  847.                 SetItemStyle(menu, item, italic);
  848.             else if (Documents[i]->theWindow == front)
  849.                 SetItemMark(menu, item, checkMark);
  850.             
  851.             EnableItem(menu, item);
  852.             needsSeparator = 1;
  853.         }
  854.     
  855.     for (i = 0; i < DocCount; ++i)
  856.         if (Documents[i]->kind == kDocumentWindow) {
  857.             if (needsSeparator && needsSeparator < 2) {
  858.                 AppendMenu(menu, (StringPtr) "\p-(");
  859.                 ++item;
  860.             }
  861.             
  862.             AppendMenu(menu, (StringPtr) "\px");
  863.             GetWTitle(Documents[i]->theWindow, name);
  864.             SetMenuItemText(menu, ++item, name);
  865.             
  866.             if (!((WindowPeek) Documents[i]->theWindow)->visible)
  867.                 SetItemStyle(menu, item, Documents[i]->dirty ? underline + italic : italic);
  868.             else {
  869.                 if (Documents[i]->dirty)
  870.                     SetItemStyle(menu, item, underline);
  871.                 if (Documents[i]->theWindow == front)
  872.                     SetItemMark(menu, item, checkMark);
  873.             }
  874.             
  875.             EnableItem(menu, item);
  876.             needsSeparator = 2;
  877.         }
  878.     
  879.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  880.         nextWindow = aWindow->nextWindow;
  881.         if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
  882.             if (needsSeparator && needsSeparator < 3) {
  883.                 AppendMenu(menu, (StringPtr) "\p-(");
  884.                 ++item;
  885.             }
  886.             
  887.             AppendMenu(menu, (StringPtr) "\px");
  888.             GetWTitle((WindowPtr) aWindow, name);
  889.             SetMenuItemText(menu, ++item, name);
  890.             
  891.             if ((WindowPtr) aWindow == front)
  892.                 SetItemMark(menu, item, checkMark);
  893.             
  894.             EnableItem(menu, item);
  895.             needsSeparator = 3;
  896.         }
  897.     }
  898. }
  899.  
  900. static void AnointWindow(WindowPtr win)
  901. {
  902.     if (!((WindowPeek) win)->visible)
  903.         ShowWindow(win);
  904.     SelectWindow(win);
  905. }
  906.  
  907. pascal void DoSelectWindow(short item)
  908. {
  909.     short            i;
  910.      WindowPeek    aWindow;
  911.     WindowPeek    nextWindow;
  912.     MenuHandle    menu;
  913.     int             needsSeparator = 0;
  914.     
  915.     menu = myMenus[windowM];
  916.     
  917.     for (i = 0; i < DocCount; ++i)
  918.         if (Documents[i]->kind != kDocumentWindow) {
  919.             if (!--item) {
  920.                 AnointWindow(Documents[i]->theWindow);
  921.                 
  922.                 return;
  923.             }
  924.             needsSeparator = 1;
  925.         }
  926.     
  927.     for (i = 0; i < DocCount; ++i)
  928.         if (Documents[i]->kind == kDocumentWindow) {
  929.             if (needsSeparator && needsSeparator < 2) {
  930.                 --item;
  931.             }
  932.             
  933.             if (!--item) {
  934.                 AnointWindow(Documents[i]->theWindow);
  935.                 
  936.                 return;
  937.             }
  938.             
  939.             needsSeparator = 2;
  940.         }
  941.     
  942.     for (aWindow = (WindowPeek) FrontWindow(); aWindow; aWindow = nextWindow) {
  943.         nextWindow = aWindow->nextWindow;
  944.         if (aWindow->visible && !Ours((WindowPtr) aWindow)) {
  945.             if (needsSeparator && needsSeparator < 3) {
  946.                 --item;
  947.             }
  948.             
  949.             if (!--item) {
  950.                 AnointWindow((WindowPtr) aWindow);
  951.                 
  952.                 return;
  953.             }
  954.             
  955.             needsSeparator = 3;
  956.         }
  957.     }
  958. }
  959.  
  960. /* Borrowed from tech note 263 */
  961.  
  962. #define kKosherModifiers    0x0E00        // We keep only option & shift
  963. #define kMaskVirtualKey     0x0000FF00     // get virtual key from event message
  964.                                            // for KeyTrans
  965. #define kUpKeyMask          0x0080
  966. #define kShiftWord          8              // we shift the virtual key to mask it
  967.                                            // into the keyCode for KeyTrans
  968. #define kMaskASCII1         0x00FF0000     // get the key out of the ASCII1 byte
  969. #define kMaskASCII2         0x000000FF     // get the key out of the ASCII2 byte
  970.  
  971. pascal Boolean WeirdChar(const EventRecord * ev, short modifiers, char ch)
  972. {
  973.       short    keyCode;
  974.       long     virtualKey, keyInfo, lowChar, highChar, state, keyCId;
  975.       Handle   hKCHR;
  976.     Ptr         KCHRPtr;
  977.  
  978.     if ((ev->what == keyDown) || (ev->what == autoKey)) {
  979.  
  980.         // see if the command key is down.  If it is, find out the ASCII
  981.         // equivalent for the accompanying key.
  982.  
  983.         if ((ev->modifiers & 0xFF00) == modifiers) {
  984.  
  985.             virtualKey     = (ev->message & kMaskVirtualKey) >> kShiftWord;
  986.             keyCode          = (ev->modifiers & kKosherModifiers & ~modifiers) | virtualKey;
  987.             state           = 0;
  988.  
  989.             hKCHR            = nil;  /* set this to nil before starting */
  990.              KCHRPtr         = (Ptr)GetEnvirons(smKCHRCache);
  991.  
  992.             if ( !KCHRPtr ) {
  993.                 keyCId     =    GetScript((short) GetEnvirons(smKeyScript), smScriptKeys);
  994.                 hKCHR        =    GetResource('KCHR', (short) keyCId);
  995.                 KCHRPtr    = *hKCHR;
  996.             }
  997.  
  998.             if (KCHRPtr) {
  999.                 keyInfo = KeyTrans(KCHRPtr, keyCode, &state);
  1000.                 if (hKCHR)
  1001.                     ReleaseResource(hKCHR);
  1002.             } else
  1003.                 keyInfo = ev->message;
  1004.  
  1005.             lowChar =  keyInfo &  kMaskASCII2;
  1006.             highChar = (keyInfo & kMaskASCII1) >> 16;
  1007.             if (lowChar == ch || highChar == ch)
  1008.                 return true;
  1009.  
  1010.         }  // end the command key is down
  1011.     }  // end key down event
  1012.  
  1013.     return false;
  1014. }
  1015.  
  1016.  
  1017. pascal Boolean SameFSSpec(FSSpec * one, FSSpec * other)
  1018. {
  1019.     return     one->vRefNum    ==        other->vRefNum 
  1020.         &&        one->parID        ==        other->parID
  1021.         &&     EqualString(one->name, other->name, false, true);
  1022. }
  1023.